import { AttributeType } from './AttributeType';
import { AttributeValue } from './AttributeValue';
import { AttributeModifier } from './AttributeModifier';
import { AttributeDependency } from './AttributeDependency';
import { Equipment } from './Equipment';
import { ModifierType } from './ModifierType';

export class BattleUnit {
    private attributes: Map<AttributeType, AttributeValue>;
    private modifiers: Map<AttributeType, AttributeModifier[]>;
    private cachedValues: Map<AttributeType, number>;
    private isDirty: Map<AttributeType, boolean>;
    private dependency: AttributeDependency;
    private equipment: Equipment | null;

    constructor() {
        this.attributes = new Map();
        this.modifiers = new Map();
        this.cachedValues = new Map();
        this.isDirty = new Map();
        this.dependency = new AttributeDependency();
        this.equipment = null;
    }

    public setAttribute(type: AttributeType, value: number): void {
        this.attributes.set(type, new AttributeValue(value));
        this.markDirty(type);
    }

    public getAttributeValue(type: AttributeType): number {
        // 如果缓存有效，直接返回缓存值
        if (!this.isDirty.get(type) && this.cachedValues.has(type)) {
            return this.cachedValues.get(type)!;
        }

        const attribute = this.attributes.get(type);
        if (!attribute) {
            return 0;
        }

        const baseValue = attribute.getBaseValue();
        const typeModifiers = this.modifiers.get(type) || [];
        
        // 添加装备的modifiers
        if (this.equipment) {
            const equipmentModifiers = this.equipment.getModifiers().get(type) || [];
            typeModifiers.push(...equipmentModifiers);
        }
        
        // Sort modifiers by priority
        const sortedModifiers = [...typeModifiers].sort((a, b) => b.priority - a.priority);
        
        // Calculate total modification
        let totalModification = 0;
        for (const modifier of sortedModifiers) {
            let modifierValue;
            if (modifier.type === ModifierType.ATTRIBUTE_BASED && modifier.basedOnAttribute) {
                const basedOnValue = this.getAttributeValue(modifier.basedOnAttribute);
                modifierValue = modifier.apply(baseValue, basedOnValue);
            } else {
                modifierValue = modifier.apply(baseValue);
            }
            totalModification += (modifierValue - baseValue);
        }

        const finalValue = baseValue + totalModification;
        
        // 更新缓存
        this.cachedValues.set(type, finalValue);
        this.isDirty.set(type, false);

        return finalValue;
    }

    public addModifier(type: AttributeType, modifier: AttributeModifier): void {
        if (!this.modifiers.has(type)) {
            this.modifiers.set(type, []);
        }
        this.modifiers.get(type)!.push(modifier);
        this.markDirty(type);
    }

    public removeModifier(type: AttributeType, modifier: AttributeModifier): void {
        const typeModifiers = this.modifiers.get(type);
        if (typeModifiers) {
            const index = typeModifiers.indexOf(modifier);
            if (index !== -1) {
                typeModifiers.splice(index, 1);
                this.markDirty(type);
            }
        }
    }

    public takeDamage(damage: number): void {
        const currentHP = this.getAttributeValue(AttributeType.HP);
        const newHP = Math.max(0, currentHP - damage);
        const attribute = this.attributes.get(AttributeType.HP);
        if (attribute) {
            attribute.setCurrentValue(newHP);
            this.markDirty(AttributeType.HP);
        }
    }

    public isDead(): boolean {
        return this.getAttributeValue(AttributeType.HP) <= 0;
    }

    public equip(equipment: Equipment): void {
        this.equipment = equipment;
        // 标记所有受装备影响的属性为dirty
        for (const [type] of equipment.getModifiers()) {
            this.markDirty(type);
        }
    }

    public unequip(): void {
        if (this.equipment) {
            // 标记所有受装备影响的属性为dirty
            for (const [type] of this.equipment.getModifiers()) {
                this.markDirty(type);
            }
            this.equipment = null;
        }
    }

    public addAttributeDependency(source: AttributeType, target: AttributeType): void {
        this.dependency.addDependency(source, target);
    }

    public removeAttributeDependency(source: AttributeType, target: AttributeType): void {
        this.dependency.removeDependency(source, target);
    }

    private markDirty(type: AttributeType): void {
        this.isDirty.set(type, true);
        
        // 标记所有依赖此属性的属性为dirty
        const dependentAttributes = this.dependency.getDependentAttributes(type);
        for (const dependentType of dependentAttributes) {
            this.markDirty(dependentType);
        }
    }
} 